/*
srkrt_dynamic_stack.c
Ce fichier contient le corps des fonctions utilisées pour manipuler la pile.
*/
#include "srkrt_dynamic_stack.h"
#include <stdlib.h>
#include <stdio.h>

/* ---------------------------------------
	Declaration des fonctions 
--------------------------------------- */

Stack stack_create(void) {

	Stack s;
	s.head = NULL;
	s.size = 0;
	return(s);
}

Stack stack_create_copy_revert(Stack *from) {
	Stack to = stack_create();
	Stack tmp = stack_create();
	Move move;

	while ( !stack_is_empty(from) ) {
		/* on recupere la tete*/
		move = stack_head(from);
		/* on depile from */
		stack_remove(from);
		/* on empile la tete dans la nouvelle pile */
		stack_add(&to, move);
		stack_add(&tmp, move);
	}

	while ( !stack_is_empty(&tmp) ) {
		/* on recupere la tete*/
		move = stack_head(&tmp);
		/* on depile tmp */
		stack_remove(&tmp);
		/* on empile la tete dans la nouvelle pile */
		stack_add(from, move);
	}

	return(to);
}

bool stack_is_empty(Stack* s) {
	
	if ( s == NULL ) {
		fprintf(stderr, "Erreur in stack_is_empty() : la pile n'est pas initialise !\n");
	}
        return(!s->size);
}

void stack_add(Stack* s, Move m) {

        Cel* new = NULL;
                
        /* création de la nouvelle cellule */
        new = (Cel*)malloc(sizeof(Cel));
        
        if ( new == NULL ) {
	        fprintf(stderr, "Erreur in stack_add(), allocation impossible\n");
        } else {
		/* on lie la nouvelle cellule au reste de la pile */
		new->next = s->head;  

		/* on affecte l'élément */
		new->value = m;
		
		/* on lie la Pile à la nouvelle cellule */
		s->head = new;
		
		/* on incrémente la taille */
		(s->size)++;
        }

}

void stack_remove(Stack* s) {
	
        Cel* del;
        
        if (stack_is_empty(s)) { /* si la pile est vide */ 
	        fprintf(stderr, "Erreur in stack_remove(), la pile est vide !\n");
        } else {
        
		/* on recupere l'adresse de la cellule a supprimer */
		del = s->head;
		/* on lie la pile à la seconde cellule */
		s->head = s->head->next;
		/* on libère la mémoire */
		free(del);
		/* on décrémente size */
		(s->size)--;
        }
}

void stack_destroy(Stack* stack) {

	Cel* current;
	Cel* next;
	current = stack->head;
	
	while ( (current != NULL) ) {
		/* on supprime la cellule */
		next = current->next;
		stack_remove(stack);
		/* on passe à la Cel suivante */
		current = next;
	}
}

Move stack_head(Stack* s) {
        
	if (stack_is_empty(s)) { /* si la pile est vide */ 
		fprintf(stderr, "Erreur in stack_head(), la pile est vide !\n");
	}
	return ((s->head)->value);
}

unsigned int stack_size(Stack* s) {
	
	if ( s == NULL ) { /* si la pile n'est pas initialise */
		fprintf(stderr, "Erreur in stack_size, la pile n'est pas initialisé !");
	}
	return(s->size);
	
}
